package com.tlgen.orm.utils.http;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.tlgen.orm.components.rest.model.RequestMappingClasses;
import com.tlgen.orm.components.rest.model.RequestMethodAndUrl;
import com.tlgen.orm.components.serializer.JsonResponseProcessor;
import com.tlgen.orm.model.R;
import com.tlgen.orm.param.FieldParam;
import com.tlgen.orm.utils.log.ColorLogger;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

import static com.tlgen.orm.utils.orm.ORMUtils.getAllFields;

public class HttpUtils {

    // 使用Spring的路径匹配器（线程安全）
    private static final PathMatcher PATH_MATCHER = new AntPathMatcher();

    public static void writeResponse(HttpServletResponse response, Object result) throws IOException {
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding("UTF-8");
        Object data = JsonResponseProcessor.processResponse(result);
        if (Objects.nonNull(data)) {
            ColorLogger.printSuccessMessage(ColorLogger.FIRE + " " + JSONObject.toJSONString(data));
        }
        R<Object> ok = R.ok(data);
        response.getWriter().write(JSONObject.toJSONString(ok));
        response.getWriter().flush();
    }

    /**
     * 获取请求中表单中参数, 并组装成 List<FieldParam>
     *
     * @param request
     */
    public static List<FieldParam> getParameterFieldParams(HttpServletRequest request) {
        List<FieldParam> fieldParams = Lists.newArrayList();
        Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String parameterName = parameterNames.nextElement();
            String[] parameterValue = request.getParameterValues(parameterName);
            if (Objects.nonNull(parameterValue)) {
                FieldParam fieldParam = new FieldParam();
                fieldParam.setName(parameterName);
                fieldParam.setValue(parameterValue[0]);
                fieldParams.add(fieldParam);
            }
        }
        return fieldParams;
    }

    /**
     * 获取请求体中的参数, 并组装成 List<FieldParam>
     *
     * @param request
     * @return
     */
    public static List<FieldParam> getRequestJsonFieldParams(HttpServletRequest request) {
        String requestJson = getRequestJson(request);
        if (StringUtils.isBlank(requestJson)) {
            return Collections.emptyList();
        }
        try {
            Object parsed = JSON.parse(requestJson);
            return parseNode("root", parsed);
        } catch (Exception e) {
            throw new RuntimeException("JSON解析失败", e);
        }
    }

    private static List<FieldParam> parseNode(String name, Object node) {
        FieldParam param = new FieldParam().setName(name);

        if (node instanceof JSONObject) {
            param.setDataStructure(FieldParam.DataStructure.OBJECT)
                    .setType(Map.class);

            JSONObject obj = (JSONObject) node;
            for (String key : obj.keySet()) {
                param.getChildren().addAll(parseNode(key, obj.get(key)));
            }

        } else if (node instanceof JSONArray) {
            param.setDataStructure(FieldParam.DataStructure.ARRAY)
                    .setType(List.class);

            JSONArray arr = (JSONArray) node;
            for (int i = 0; i < arr.size(); i++) {
                param.getChildren().addAll(parseNode("["+i+"]", arr.get(i)));
            }

        } else {
            // 处理基础类型
            param.setDataStructure(FieldParam.DataStructure.PRIMITIVE)
                    .setType(node != null ? node.getClass() : Void.class)
                    .setValue(node);
        }

        return Collections.singletonList(param);
    }

    /**
     * 获取接口请求参数
     *
     * @param request
     * @return
     */
    public static List<FieldParam> getRequestFieldParams(HttpServletRequest request) {
        // 获取表单参数
        List<FieldParam> fieldParams = getParameterFieldParams(request);
        // 获取 json 参数
        if (fieldParams.isEmpty()) {
            fieldParams = getRequestJsonFieldParams(request);
        }
        return fieldParams;
    }

    /**
     * 将接口请求参数转换成 JSON 字符串
     *
     * @param requestFieldParams
     * @return
     */
    public static String requestFieldParamsToJsonString(List<FieldParam> requestFieldParams) {
        JSONObject jsonObject = new JSONObject();
        for (FieldParam requestFieldParam : requestFieldParams) {
            jsonObject.put(requestFieldParam.getName(), requestFieldParam.getValue());
        }
        return jsonObject.toJSONString();
    }

    /**
     * 获取请求体中的 JSON 数据
     *
     * @param request
     * @return
     */
    public static String getRequestJson(HttpServletRequest request) {
        StringBuilder buffer = new StringBuilder();
        try {
            BufferedReader reader = request.getReader();
            String line;
            while ((line = reader.readLine()) != null) {
                buffer.append(line);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return buffer.toString();
    }

    /**
     * 智能获取匹配的请求方法和URL，并提取路径参数
     *
     * @param requestMappingClasses 请求映射类列表
     * @param requestUri 请求的实际URI
     * @return 包含路径参数的RequestMethodAndUrl对象
     */
    public static RequestMethodAndUrl getCurrentRequestMethodAndUrl(
            List<RequestMappingClasses> requestMappingClasses,
            String requestUri) {

        // 1. 获取所有可能的匹配项
        List<RequestMethodAndUrl> candidates = requestMappingClasses.stream()
                .flatMap(rmc -> rmc.getRequestMethodAndUrls().stream())
                .collect(Collectors.toList());

        // 2. 找到最匹配的URL模式
        String bestMatchPattern = findBestMatchPattern(candidates, requestUri);
        if (bestMatchPattern == null) return null;

        // 3. 提取路径参数
        Map<String, String> pathVariables = extractPathVariables(bestMatchPattern, requestUri);

        // 4. 找到对应的RequestMethodAndUrl对象
        RequestMethodAndUrl result = candidates.stream()
                .filter(rmau -> rmau.getUrl().equals(bestMatchPattern))
                .findFirst()
                .orElse(null);

        // 5. 添加路径参数到结果中
        if (result != null) {
            List<FieldParam> pathParams = convertToFieldParams(pathVariables);
            result.setArgs(pathParams.toArray(new Object[0]));
        }

        return result;
    }

    /**
     * 找到最匹配的URL模式
     */
    private static String findBestMatchPattern(List<RequestMethodAndUrl> candidates, String requestUri) {
        String bestMatch = null;
        int bestScore = Integer.MIN_VALUE;

        for (RequestMethodAndUrl candidate : candidates) {
            String pattern = candidate.getUrl();
            int score = calculateMatchScore(pattern, requestUri);
            if (score > bestScore) {
                bestMatch = pattern;
                bestScore = score;
            }
        }
        return bestMatch;
    }

    /**
     * 计算匹配度分数
     */
    private static int calculateMatchScore(String pattern, String requestUri) {
        // 1. 完全匹配得最高分
        if (pattern.equals(requestUri)) {
            return 100;
        }

        // 2. 路径模式匹配
        if (PATH_MATCHER.match(pattern, requestUri)) {
            int score = 50;

            // 减少通配符数量得分更高
            score -= countOccurrences(pattern, '*') * 5;

            // 减少路径变量数量得分更高
            score -= countOccurrences(pattern, '{') * 3;

            // 更具体的路径得分更高
            score += countOccurrences(pattern, '/') * 2;

            return score;
        }

        // 3. 忽略查询参数匹配
        String basePattern = pattern.split("\\?")[0];
        String baseRequest = requestUri.split("\\?")[0];
        if (basePattern.equals(baseRequest)) {
            return 30;
        }

        return -1; // 无匹配
    }

    /**
     * 提取路径参数
     */
    private static Map<String, String> extractPathVariables(String pattern, String path) {
        if (!pattern.contains("{")) {
            return Collections.emptyMap();
        }
        return PATH_MATCHER.extractUriTemplateVariables(pattern, path);
    }

    /**
     * 将路径参数映射转换为FieldParam列表
     */
    private static List<FieldParam> convertToFieldParams(Map<String, String> pathVariables) {
        return pathVariables.entrySet().stream()
                .map(entry -> new FieldParam(
                        String.class,
                        entry.getKey(),
                        entry.getValue()
                ))
                .collect(Collectors.toList());
    }

    /**
     * 计算字符出现次数
     */
    private static int countOccurrences(String str, char ch) {
        return (int) str.chars().filter(c -> c == ch).count();
    }

    public static <T> List<FieldParam> getQueryRequestFieldParams(List<FieldParam> fieldParams, Class<?> tClass) {
        // 获取实体类的所有字段名（下划线格式）
        Set<String> validFields = getAllFields(tClass).stream()
                .map(Field::getName)
                .collect(Collectors.toSet());
        // 过滤出有效的请求参数
        return fieldParams.stream()
                .filter(param -> validFields.contains(param.getName()))
                .collect(Collectors.toList());
    }

}
